package com.txts.road.admin.beidou.api.v1.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.txts.road.admin.beidou.api.v1.model.MessageEntity;
import com.txts.road.admin.beidou.api.v1.model.MessageReceiveRequest;
import com.txts.road.admin.beidou.api.v1.model.MessageReceiveResponse;
import com.txts.road.admin.beidou.api.v1.model.vo.MessageVO;
import com.txts.road.admin.beidou.api.v1.service.BeidouMessageService;
import com.txts.road.admin.beidou.api.v1.util.BeidouMessageParser;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.function.BiFunction;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author baoyr
 * @version 1.0
 * @description: 北斗接口实现类
 * @date 2025/7/24 17:55
 */
@Slf4j
@Service("beidouMessageService")
public class BeidouMessageServiceImpl implements BeidouMessageService {

    @Resource
    private JdbcTemplate jdbcTemplate;

    private static final DateTimeFormatter DTF_SPACE = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");


    @Override
    public MessageReceiveResponse receive(String requestId, MessageReceiveRequest request) {
        // 1. 调用底层解析器，获得原始“人可读”文本
        BeidouMessageParser.ParsedMessage parsed = null;
        try {
            parsed = BeidouMessageParser.parseContent(request.getContent());
        } catch (Exception e) {
            MessageReceiveResponse err = new MessageReceiveResponse();
            err.setRequestId(requestId);
            err.setCode("parse_error");
            return err;
        }
        String text = parsed.toString();  // 假设 toString() 返回：
        // Header: …\nType: …\nTime: …\nFreq: …\nCount: …\nP1: …\n…\nChecksum: …

        // 2. 定义一个工具方法，按正则提取单个字段
        BiFunction<String, String, String> extract = (input, regex) -> {
            Matcher m = Pattern.compile(regex, Pattern.MULTILINE).matcher(input);
            return m.find() ? m.group(1).trim() : null;
        };

        // 3. 用正则依次提取所有字段
        String header = extract.apply(text, "^Header:\\s*(.+)$");
        String type = extract.apply(text, "^Type:\\s*(.+)$");
        String timeParsed = extract.apply(text, "^Time:\\s*(.+)$");
        String freq = extract.apply(text, "^Freq:\\s*(.+)$");
        String countStr = extract.apply(text, "^Count:\\s*(\\d+)$");
        String p1 = extract.apply(text, "^P1:\\s*(.+)$");
        String p2 = extract.apply(text, "^P2:\\s*(.+)$");
        String p3 = extract.apply(text, "^P3:\\s*(.+)$");
        String p4 = extract.apply(text, "^P4:\\s*(.+)$");
        String checksum = extract.apply(text, "^Checksum:\\s*(.+)$");

        // 4. 拼接 P1~P4 为一个字段
        String positions = Stream.of(p1, p2, p3, p4)
                .filter(Objects::nonNull)
                .collect(Collectors.joining("\n"));

        // 5. 执行 INSERT（假设 request.getTime() 和 timeParsed 都是 ISO‑8601）
        String sql = "INSERT INTO message_all " +
                "(id_number, content, time, message_id, delivery_count, message_type, code_type, network_mode, " +
                "header, parsed_type, parsed_time, freq, parsed_count, positions, checksum) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
        jdbcTemplate.update(sql,
                request.getIdNumber(),
                request.getContent(),
                Timestamp.valueOf(LocalDateTime.parse(request.getTime(), DTF_SPACE)),
                request.getMessageId(),
                Integer.parseInt(request.getDeliveryCount()),
                request.getMessageType(),
                request.getCodeType(),
                request.getNetworkMode(),
                header,
                type,
                Timestamp.valueOf(LocalDateTime.parse(timeParsed, DTF_SPACE)),
                freq,
                Integer.parseInt(countStr),
                positions,
                checksum
        );

        MessageReceiveResponse resp = new MessageReceiveResponse();
        resp.setRequestId(requestId);
        resp.setCode("ok");
        return resp;
    }

    @Override
    public MessageVO getLatestMessageByIdNumber(String idNumber) {
        String sql = "SELECT * FROM message_all " +
                "WHERE id_number = ? " +
                "ORDER BY parsed_time DESC " +
                "LIMIT 1";
        return jdbcTemplate.queryForObject(
                sql,
                new Object[]{idNumber},
                new BeanPropertyRowMapper<>(MessageVO.class)
        );
    }

    @Override
    public Map<String, Object> getFenceGeoJson() {
        String sql = "SELECT `types`, polygon_coords, fence_name FROM fence_info";
        List<Map<String, Object>> records = jdbcTemplate.queryForList(sql);
        List<Map<String, Object>> features = new ArrayList<>();
        ObjectMapper mapper = new ObjectMapper();

        for (Map<String, Object> record : records) {
            try {
                int type = Integer.parseInt(record.get("types").toString());
                String name = record.get("fence_name").toString();
                String coordsJson = record.get("polygon_coords").toString();

                // 解析 polygon_coords
                List<List<Double>> coords = mapper.readValue(
                        coordsJson, new TypeReference<List<List<Double>>>() {
                        }
                );

                // 闭环处理：首尾不一样则加上第一个点
                if (!coords.isEmpty() && !coords.get(0).equals(coords.get(coords.size() - 1))) {
                    coords.add(new ArrayList<>(coords.get(0)));
                }

                // 构造 geometry 对象
                Map<String, Object> geometry = new HashMap<>();
                geometry.put("type", "MultiPolygon");
                geometry.put("coordinates", Collections.singletonList(Collections.singletonList(coords)));

                // 构造 properties 对象
                Map<String, Object> properties = new HashMap<>();
                properties.put("Id", 0);
                properties.put("type", type);
                properties.put("name", name);

                // 构造 feature 对象
                Map<String, Object> feature = new HashMap<>();
                feature.put("type", "Feature");
                feature.put("properties", properties);
                feature.put("geometry", geometry);

                features.add(feature);

            } catch (Exception e) {
                log.error("Error parsing fence record: " + record);
            }
        }

        // 构造 crs 对象（GeoJSON 坐标系定义）
        Map<String, Object> crsProperties = new HashMap<>();
        crsProperties.put("name", "urn:ogc:def:crs:OGC:1.3:CRS84");

        Map<String, Object> crs = new HashMap<>();
        crs.put("type", "name");
        crs.put("properties", crsProperties);

        // 构造最终 GeoJSON 返回体
        Map<String, Object> geoJson = new HashMap<>();
        geoJson.put("type", "FeatureCollection");
        geoJson.put("name", "fence2");
        geoJson.put("crs", crs);
        geoJson.put("features", features);
        return geoJson;
    }

    @Override
    public List<MessageVO> getMessagesByTimeRange(String idNumber, LocalDateTime start, LocalDateTime end) {

        String sql = "SELECT * FROM message_all WHERE id_number = ? AND parsed_time BETWEEN ? AND ?";
        List<MessageVO> messages = jdbcTemplate.query(sql, new Object[]{
                idNumber,
                Timestamp.valueOf(start),
                Timestamp.valueOf(end)
        }, new BeanPropertyRowMapper<>(MessageVO.class));
        return messages;
    }
}
